﻿using System;
using System.ComponentModel;
using System.Data;
using System.IO;
using System.Text;
using org.se.fs.model;
using org.se.fs.presenter.ITask;
using org.se.fs.presenter.Library;

namespace org.se.fs.presenter.Task
{
    public class DatabaseConnection : IDatabaseConnection
    {
        private readonly BackgroundWorker _bgwSave;
        private readonly BackgroundWorker _bgwTestConnect;
        public event FormEvent.FormEventHandler OnTestConnectFinished;
        public event FormEvent.FormEventHandler OnOkFinished;

        public DatabaseConnection()
        {
            _bgwSave = new BackgroundWorker();
            _bgwSave.DoWork += BgwSaveDoWork;
            _bgwSave.RunWorkerCompleted += BgwSaveRunWorkerCompleted;

            _bgwTestConnect = new BackgroundWorker();
            _bgwTestConnect.DoWork += BgwTestConnectDoWork;
            _bgwTestConnect.RunWorkerCompleted += BgwTestConnectRunWorkerCompleted;
        }

        static void BgwSaveDoWork(object sender, DoWorkEventArgs e)
        {
            var fileName = Config.FileName;
            var dataTable = new DataTable();

            // Assemble DataSet
            dataTable.Columns.Add("NAME", Type.GetType("System.String"));
            dataTable.Columns.Add("VALUE", Type.GetType("System.String"));
            dataTable.TableName = "Configuration";
            dataTable.Rows.Add("ConnectionString", DataContext.ConnectionString);
            dataTable.Rows.Add("ProviderType", ProviderType.Mysql);
            
            string data;
            using (var dataSet = new DataSet())
            {
                dataSet.Tables.Add(dataTable);

                // Encrypt XML
                data = Cryptography.Encrypt(dataSet.GetXml(), Config.PassPhrase, Config.SaltValue, Config.HashAlgorithm, Config.PasswordIterations, Config.InitVector, Config.KeySize);
            }

            // Delete file if already exist
            if (File.Exists(fileName))
                File.Delete(fileName);

            // Create config file
            using (var fs = File.Open(fileName, FileMode.CreateNew, FileAccess.Write))
            using (var sw = new StreamWriter(fs, Encoding.UTF8))
                sw.WriteLine(data);
        }

        void BgwSaveRunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
        {
            OnOkFinished(this, new FormEvent(File.Exists(Config.FileName)));
        }

        public void SaveConfiguration(string user, string password, string server, string database)
        {
            DataContext.ConnectionString = DataContext.GetConnectionString(user, password, server, database);
            _bgwSave.RunWorkerAsync(new[] { DataContext.ConnectionString });
        }

        public void TestConnect(string user, string password, string server, string database)
        {
            var connectionString = DataContext.GetConnectionString(user, password, server, database);
            _bgwTestConnect.RunWorkerAsync(connectionString);
        }

        static void BgwTestConnectDoWork(object sender, DoWorkEventArgs e)
        {
            e.Result = new Validator().TestConnection(e.Argument.ToString());
        }

        void BgwTestConnectRunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
        {
            OnTestConnectFinished(this, new FormEvent((bool)e.Result));
        }
    }
}